Bitshares 开发者系列(1)—— Api接口的访问方式
官方接口访问库 GitHub : https://github.com/bitshares/bitsharesjs-ws
在阅读源码之前,最好先浏览一遍 Bitshares 官方公开的开发文档,虽然文档中对开发细节描述的不是很清楚,但也能对系统的通讯方式有个详细的了解。
Graphene API 通讯方式
Bitshares 系统共支持两种 API 调用方式:
- WebSocket Calls - 长连接调用
- Remote Procedure Calls - HTTP 方式调用
官方 GitHub 仓库提供的 GUI 钱包客户端 bitshares-ui
就是使用 WebSocket 方式通讯的,此钱包客户端是使用 React
开发的前端工程,然后使用 Electron
工具打包成了各平台可用的桌面客户端,这样做的优势在于,技术栈全部使用前端技术,可以做功能的一次性开发,然后使用相关的打包工具,进行跨平台的客户端打包,能够同时进行 Web
端和 桌面客户端
的开发。
关于 Bitshares
官方的 GitHub 账号开源的几个项目,作一下简要的介绍,其中,bitshares-ui
项目依赖 bitsharesjs
, 而 bitsharesjs
又依赖 bitsharesjs-ws
项目,它们之间的职责关系如下:
bitshares-ui
完整的钱包客户端项目,使用 React + Electron 技术栈,同时支持 Web 和 桌面客户端的打包。bitsharesjs
API业务工具,基层依赖 bitsharesjs-ws 项目进行API通讯,其模块内部封装并完成了大部分的业务API。bitsharesjs-ws
针对 Graphene 系统定制的 WebSocket 接口访问通信工具,封装并定制了系统特有的API访问流程。
WebSocket 调用 API 数据结构
1 | { |
id
字段的作用是专门针对 WebSocket 方式的 API 定制的,我们知道 WebSocket 是长连接协议,像 Socket 编程一样,可以发送二进制和文本类型的数据。但是发送数据和返回数据之间是无序的,你可能发送的顺序是 A-api、B-api ,然而服务器端响应给你的顺序却可能是 B-result、A-result。
所以 API 在设计的时候特限定了一个id
字段,当你发起 API 调用的时候指定一个唯一id
,那么在响应结果里面,会把这个id
再返回给你,你就可以根据这个id
来区别响应结果应该怎么处理。
另外需要注意的就是
params
字段,此字段是一个数组类型,第一个元素代表API 标识符
,第二个元素代表要调用的API 名称
,第三个元素同样是一个数组类型,其数组中的每一个元素都将作为 API 的一个参数传递,并且应该注意参数的顺序与格式。
API 调用流程
Bitshares 系统的完整客户端节点提供了一系列可以通过 WebSocket 方式访问的API,但根据官方文档中描述的API调用流程,应该首先有一个初始化的调用过程:
- 1.首先应该登录到完整节点 :
1
{"id":0, "method":"call", "params":[1, "login", ["",""]]}
- 2.然后获取指定类型的API标识 :
1
2
3
4
5// 你可以动态的修改 “database” 属性,来获取不同的 API 类型请求标识。
{"id":0, "method":"call", "params":[1, "database", []]}
// 此次请求调用返回结果里面的 "result" 值,就是 "database" 类型 API 的标识符。
{"id":2, "result":2}
- 3.你可以多次的进行第二步操作,拿到不同类型的 API 标识符,最后只需要之前介绍过的 API 数据结构指定好
id
与params
参数格式,即可调用所有公开的 API 接口。
API 返回结果数据格式
调用成功 JSON 格式 :
1
2
3
4 {
"id" : 1, // 调用 API 时传递的调用标识。
"result" : ...data...
}
调用失败 JSON 格式 :
1
2
3
4
5
6
7
8
9
10
11
12 {
"id" : 0, // 调用 API 时传递的调用标识。
"data" : {
"code" : 1,
"error" : {
"code" : error-code,
"name" : " .. name of exception .."
"message" : " .. message of exception ..",
"stack" : [ .. stack trace .. ],
},
},
}
API 是否调用成功,可以简单的通过判断结果是否包含 resutl
字段来区分,假如包含 result
字段就可以认为调用成功,不同 API 有不同的 result
结构,届时根据 API 文档,分别进行解析处理即可。